import json

import cloudscraper
import requests
from flask import Flask, render_template, request, redirect, url_for, flash, g, session, jsonify, make_response
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime, timedelta
import os
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
from werkzeug.security import generate_password_hash, check_password_hash

app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(24).hex()
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///alpha_scores.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)

# 初始化Flask-Login
login_manager = LoginManager(app)
login_manager.login_view = 'login'


# 用户模型
class User(UserMixin, db.Model):
    __tablename__ = 'tb_users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(50), unique=True, nullable=False)
    password_hash = db.Column(db.String(128), nullable=False)
    accounts = db.Column(db.JSON)  # 存储关联的account列表

    def set_password(self, password):
        self.password_hash = generate_password_hash(password)

    def check_password(self, password):
        return check_password_hash(self.password_hash, password)


@app.template_filter('add_days')
def add_days_filter(date, days):
    # 自定已过滤器用于添加指定天数
    if isinstance(date, str):
        date = datetime.strptime(date, '%Y-%m-%d')
    return date + timedelta(days=days)


# 用户加载器
@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))


def fetch_alpha123_data(url):
    try:
        # 创建 Cloudscraper 实例
        scraper = cloudscraper.create_scraper()

        # 请求外部API
        response = scraper.get(url, timeout=5)

        # 检查响应状态
        if response.status_code != 200:
            return jsonify({'error': f'外部API返回错误: {response.status_code}'}), 502

        # 检查内容类型
        content_type = response.headers.get('Content-Type', '')

        # 处理JSON数据
        if 'application/json' in content_type:
            # 直接返回获取的JSON数据
            return make_response(response.content, 200, {'Content-Type': 'application/json'})
        else:
            # 尝试解析为JSON
            try:
                data = response.json()
                return jsonify(data)
            except:
                # 返回原始内容以便调试
                return make_response(response.content, 200, {'Content-Type': 'text/plain'})

    except Exception as e:
        return jsonify({'error': f'处理数据时出错: {str(e)}'}), 500


# 注册路由
@app.route('/register', methods=['GET', 'POST'])
def register():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        accounts = [a.strip() for a in request.form['accounts'].split(',')]

        if User.query.filter_by(username=username).first():
            flash('用户名已存在')
            return redirect(url_for('register'))

        # 验证账号有效性
        valid_accounts = []
        for account in accounts:
            if AlphaScore.query.filter_by(account=account).first():
                valid_accounts.append(account)
            else:
                flash(f'账号 {account} 不存在，已自动过滤')

        # if not valid_accounts:
        #     flash('至少需要关联一个有效账号')
        #     return redirect(url_for('register'))

        new_user = User(
            username=username,
            accounts=valid_accounts
        )
        new_user.set_password(password)

        db.session.add(new_user)
        db.session.commit()
        flash('注册成功，请登录')
        return redirect(url_for('login'))

    return render_template('register.html')


# 登录路由
@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        user = User.query.filter_by(username=username).first()

        if user and user.check_password(password):
            login_user(user)
            next_page = request.args.get('next')
            return redirect(next_page or url_for('index'))
        else:
            flash('用户名或密码错误')
    return render_template('login.html')


# 退出路由
@app.route('/logout')
@login_required
def logout():
    logout_user()
    return redirect(url_for('index'))


class AlphaScore(db.Model):
    __tablename__ = 'tb_alpha_score'
    id = db.Column(db.Integer, primary_key=True)
    account = db.Column(db.String(50), nullable=False)
    date = db.Column(db.Date, nullable=False)
    balance = db.Column(db.Integer, default=0)
    transaction = db.Column(db.Integer, default=0)
    consumption = db.Column(db.Integer, default=0)
    remark = db.Column(db.String(200))


def initialize_database():
    with app.app_context():
        db.create_all()


@app.before_request
def check_database_initialization():
    if not hasattr(g, 'db_initialized'):
        initialize_database()
        g.db_initialized = True


def get_valid_scores():
    cutoff_date = datetime.now().date() - timedelta(days=15)
    return AlphaScore.query.filter(AlphaScore.date >= cutoff_date)


@app.before_request
def before_request():
    # 从session中获取筛选账号
    g.account_filter = session.get('account_filter', '')


def get_scores(account_filter, start_date, end_date):
    # 构建基础查询
    base_query = AlphaScore.query.filter(
        AlphaScore.date >= start_date,
        AlphaScore.date <= end_date
    )
    # 应用账号筛选
    if account_filter:
        base_query = base_query.filter(AlphaScore.account == account_filter)
    # 按日期倒序排列
    scores = base_query.order_by(AlphaScore.date.desc()).all()
    return scores


@app.route('/')
@login_required
def index():
    account_filter = request.args.get('account', '')
    if account_filter:
        session['account_filter'] = account_filter
    else:
        account_filter = session.get('account_filter', '')

    today = datetime.now().date()

    # 计算日期范围（前15天，不包括当天）
    start_date = today - timedelta(days=15)
    end_date = today - timedelta(days=1)

    scores = get_scores(account_filter, start_date, end_date)
    tomorrow_cores = get_scores(account_filter, start_date + timedelta(days=1), today)
    # 获取当天记录（同样应用账号筛选）
    today_query = AlphaScore.query.filter(AlphaScore.date == today)
    if account_filter:
        today_query = today_query.filter(AlphaScore.account == account_filter)
    today_scores = today_query.order_by(AlphaScore.date.desc()).all()

    # 计算总积分 = 前15天（余额积分 + 交易量积分 - 消耗积分）
    total_score = 0
    total_transaction = 0
    total_consumption = 0
    tomorrow_total_score = 0

    for score in scores:
        total_score += (score.balance + score.transaction - score.consumption)
        total_transaction += score.transaction
        total_consumption += score.consumption
    # 预测明天积分
    for score in tomorrow_cores:
        tomorrow_total_score += (score.balance + score.transaction - score.consumption)

    # 获取所有账号（用于筛选下拉框）
    # all_accounts = [row[0] for row in db.session.query(AlphaScore.account).distinct().all()]
    # 筛选下拉框应限制在用户关联账户范围内：
    all_accounts = current_user.accounts
    # 计算即将回分补分的记录（未来3天内将移出统计范围的记录）
    recovery_dates = [today - timedelta(days=i) for i in range(15, 12, -1)]  # 15, 14, 13天前的记录
    recovery_records = []

    # 查询即将回分补分的记录
    recovery_query = AlphaScore.query.filter(
        AlphaScore.date.in_(recovery_dates),
        (AlphaScore.transaction == 0) | (AlphaScore.consumption > 0)
    )

    if account_filter:
        recovery_query = recovery_query.filter(AlphaScore.account == account_filter)

    recovery_records = recovery_query.order_by(AlphaScore.date.asc()).all()

    # 为每条记录计算移出日期
    for record in recovery_records:
        record.expiry_date = (record.date + timedelta(days=16)).strftime('%Y-%m-%d')

    # 获取最近的移出日期
    expiry_dates = [record.expiry_date for record in recovery_records]
    if expiry_dates:
        nearest_expiry = min(expiry_dates)
    else:
        nearest_expiry = None

    return render_template('index.html',
                           scores=scores,
                           today_scores=today_scores,
                           total_balance=total_score,
                           tomorrow_total_balance=tomorrow_total_score,
                           total_transaction=total_transaction,
                           total_consumption=total_consumption,
                           today=today,
                           account_filter=account_filter,
                           all_accounts=all_accounts,
                           recovery_records=recovery_records,
                           nearest_expiry=nearest_expiry)


@app.route('/api/airdrop_data')
@login_required
def airdrop_data():
    url = "https://alpha123.uk/api/data?fresh=1"
    return fetch_alpha123_data(url)


@app.route('/api/token_price')
@login_required
def token_price():
    url = "https://alpha123.uk/api/price/?batch=today"
    return fetch_alpha123_data(url)


@app.route('/airdrop')
@login_required
def airdrop():
    return render_template('airdrop.html')


@app.route('/add', methods=['GET', 'POST'])
@login_required
def add_score():
    # 从session中获取筛选账号
    account_filter = session.get('account_filter', '')

    if request.method == 'POST':
        account = request.form['account']
        date_str = request.form['date']
        balance = int(request.form['balance'])
        transaction = int(request.form['transaction'])
        consumption = int(request.form['consumption'])
        remark = request.form['remark']

        try:
            date = datetime.strptime(date_str, '%Y-%m-%d').date()
        except ValueError:
            flash('日期格式错误，请使用YYYY-MM-DD格式')
            return redirect(url_for('add_score'))

        new_score = AlphaScore(
            account=account,
            date=date,
            balance=balance,
            transaction=transaction,
            consumption=consumption,
            remark=remark
        )

        db.session.add(new_score)
        db.session.commit()
        flash('积分记录添加成功')
        return redirect(url_for('index'))

    # 获取当天日期字符串（格式：YYYY-MM-DD）
    today_str = datetime.now().date().strftime('%Y-%m-%d')

    return render_template('add.html', today_date=today_str, account_filter=account_filter)


@app.route('/batch_add', methods=['GET', 'POST'])
@login_required
def batch_add_score():
    account_filter = session.get('account_filter', '')
    if request.method == 'POST':
        account = request.form['account']
        start_date_str = request.form['start_date']
        end_date_str = request.form['end_date']
        balance = int(request.form['balance'])
        transaction = int(request.form['transaction'])
        consumption = int(request.form['consumption'])
        remark = request.form['remark']

        try:
            start_date = datetime.strptime(start_date_str, '%Y-%m-%d').date()
            end_date = datetime.strptime(end_date_str, '%Y-%m-%d').date()
        except ValueError:
            flash('日期格式错误，请使用YYYY-MM-DD格式')
            return redirect(url_for('batch_add_score'))

        # 确保结束日期不小于开始日期
        if end_date < start_date:
            flash('结束日期不能早于开始日期')
            return redirect(url_for('batch_add_score'))

        # 计算日期范围
        date_range = []
        current_date = start_date
        while current_date <= end_date:
            date_range.append(current_date)
            current_date += timedelta(days=1)

        # 批量添加记录
        records_added = 0
        for date in date_range:
            # 检查该日期是否已有记录
            existing_record = AlphaScore.query.filter_by(account=account, date=date).first()
            if not existing_record:
                new_score = AlphaScore(
                    account=account,
                    date=date,
                    balance=balance,
                    transaction=transaction,
                    consumption=consumption,
                    remark=remark
                )
                db.session.add(new_score)
                records_added += 1

        db.session.commit()
        flash(f'成功添加 {records_added} 条记录')
        return redirect(url_for('index'))

    # 设置默认日期范围（前15天）
    today = datetime.now().date()
    default_end_date = today - timedelta(days=1)  # 昨天
    default_start_date = today - timedelta(days=15)  # 15天前

    return render_template('batch_add.html',
                           default_start_date=default_start_date.strftime('%Y-%m-%d'),
                           default_end_date=default_end_date.strftime('%Y-%m-%d'),
                           account_filter=account_filter)


@app.route('/edit/<int:id>', methods=['GET', 'POST'])
@login_required
def edit_score(id):
    score = AlphaScore.query.get_or_404(id)

    if request.method == 'POST':
        score.account = request.form['account']
        date_str = request.form['date']
        score.balance = int(request.form['balance'])
        score.transaction = int(request.form['transaction'])
        score.consumption = int(request.form['consumption'])
        score.remark = request.form['remark']

        try:
            score.date = datetime.strptime(date_str, '%Y-%m-%d').date()
        except ValueError:
            flash('日期格式错误，请使用YYYY-MM-DD格式')
            return redirect(url_for('edit_score', id=id))

        db.session.commit()
        flash('积分记录更新成功')
        return redirect(url_for('index'))

    return render_template('edit.html', score=score)


@app.route('/delete/<int:id>')
@login_required
def delete_score(id):
    score = AlphaScore.query.get_or_404(id)
    db.session.delete(score)
    db.session.commit()
    flash('积分记录删除成功')
    return redirect(url_for('index'))


# 添加清除筛选路由
@app.route('/clear_filter')
@login_required
def clear_filter():
    if 'account_filter' in session:
        session.pop('account_filter')
    return redirect(url_for('index'))


if __name__ == '__main__':
    initialize_database()
    app.run(debug=True)
